package com.shujia.wyh.day25;

/*
        某电影院目前正在上映贺岁大片，共有100张票，而它有3个售票窗口售票，请设计一个程序模拟该电影院售票。
        两种方式实现
            2、实现Runnable接口

        为了模拟更加现实的售票场景，我们加入延迟操作
        但是呢，加入延迟之后，产生了两个问题：
            1、相同的票我们卖了很多次
                CPU的执行操作是原子性，小小的CPU时间片足矣运行很多次
            2、出了卖第0张票和负数的票。
                这个是由于线程的执行具有随机性和延迟性导致的，因为我们加入了sleep休眠方法，让线程变成阻塞状态，让其他线程执行

       上一个案例中加入了延迟操作，出现了问题，其实这个问题现象就叫做：线程安全问题
       要想解决这个问题，就得先搞清楚哪些原因导致的这个问题出现：
       （这三个条件同时满足的情况下，就会出现线程安全问题）
       1、是否存在多线程环境
       2、是否存在共享变量（共享数据）
       3、是否有多条语句操作着共享变量（共享数据）

       回想一下，上一个案例中是否都满足这个3个条件：
       1、是否存在多线程环境 存在，有3个窗口线程
       2、是否存在共享变量（共享数据） 存在，共享变量是tickets
       3、是否有多条语句操作着共享变量（共享数据） 是

       既然这3个条件都满足，由此可见上一个案例出现问题，是一个正常的现象，因为同时满足条件。

       如何解决线程安全问题呢？
       条件1，2都是我们无法改变的，我们只能想办法改变第3个条件，只要其中一个不满足，就不会发生线程安全问题。

       解决问题的思想是什么？
            要是有一个办法可以将多条操作着共享变量的代码包成一个整体，相当于给这段代码加了一把锁，在某个线程执行的时候，其他线程
            进不来就可以了。
            直到这个线程执行完后，其他线程才能进入。同一时刻，只能是一个线程操作run方法。

       java提供了一个机制给我们使用，这个机制就是用来解决线程安全问题的：同步安全机制

       解决方案一：同步代码块
        语句定义格式：
            synchronized(对象){
                需要同步的代码;
            }
            同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
            1、这里的对象是什么？
                我们先随便创建一个对象试试；
            2、需要同步的代码又是哪些呢？
                是操作共享变量的代码

 */
public class SellTicketDemo4 {
    public static void main(String[] args) {
        //创建自定义类对象
        TicketWindow4 ticketWindow4 = new TicketWindow4();

        //创建3个线程对象，模拟3个窗口进行卖票
        Thread window1 = new Thread(ticketWindow4, "窗口1");
        Thread window2 = new Thread(ticketWindow4, "窗口2");
        Thread window3 = new Thread(ticketWindow4, "窗口3");

        //启动线程
        window1.start();
        window2.start();
        window3.start();
    }
}
